#include "triangleraster.h"
#include <mymath.h>

using namespace math;

TriangleRaster::TriangleRaster()
{

}

TriangleRaster::~TriangleRaster()
{

}

void TriangleRaster::rasterTriangle(std::vector<Point> &results,
                                    const Point &v0,
                                    const Point &v1,
                                    const Point &v2)
{
    //找到需要遍历的矩形范围
    int maxX = static_cast<int>(std::max(v0.x, std::max(v1.x,v2.x)));
    int minX = static_cast<int>(std::min(v0.x, std::min(v1.x,v2.x)));
    int maxY = static_cast<int>(std::max(v0.y, std::max(v1.y,v2.y)));
    int minY = static_cast<int>(std::min(v0.y, std::min(v1.y,v2.y)));

    vec2f pv0, pv1, pv2;
    Point result;

    for(int i = minX; i <= maxX; i++)
    {
        for(int j = minY; j <= maxY; j++)
        {
            //三个向量（PA, PB,PC）
            pv0 = vec2f(v0.x - i, v0.y - j);
            pv1 = vec2f(v1.x - i, v1.y - j);
            pv2 = vec2f(v2.x - i, v2.y - j);

            //三个向量两两进行叉乘(PAxPB,PBxPC,PCxPA)(逆时针，一定是这样的叉乘)
            auto cross1 = cross(pv0,pv1);
            auto cross2 = cross(pv1,pv2);
            auto cross3 = cross(pv2,pv0);

            //叉乘结果都大于0
            bool positiveAll = cross1 > 0 && cross2 > 0 && cross3 > 0;
            //叉乘结果都小于0
            bool negativeAll = cross1 < 0 && cross2 < 0 && cross3 < 0;

            //该点在三角形内
            if(negativeAll || positiveAll)
            {
                result.x = i;
                result.y = j;

                //彩色
                interpolantTriangle(v0,v1,v2,result);
                results.push_back(result);
            }
        }

    }

}

void TriangleRaster::interpolantTriangle(const Point &v0, const Point &v1, const Point &v2, Point &p)
{
    //计算Sabc
    auto e1 = vec2f(v1.x - v0.x, v1.y - v0.y);
    auto e2 = vec2f(v2.x - v0.x, v2.y - v0.y);
    float sumArea = std::abs(cross(e1, e2)) / 2;

    //PA、PB、PC
    auto pv0 = vec2f(v0.x - p.x, v0.y - p.y);
    auto pv1 = vec2f(v1.x - p.x, v1.y - p.y);
    auto pv2 = vec2f(v2.x - p.x, v2.y - p.y);

    //计算Spbc、Spac、Spab
    float v0Area = abs(cross(pv1, pv2)) / 2;
    float v1Area = abs(cross(pv0, pv2)) / 2;
    float v2Area = abs(cross(pv0, pv1)) /2;

    //计算权重a,b,c
    float weight0 = v0Area / sumArea;
    float weight1 = v1Area / sumArea;
    float weight2 = v2Area / sumArea;

    //颜色插值
    p.color = lerpRGBA(v0.color, v1.color, v2.color,
                       weight0, weight1, weight2);

    //uv插值
    p.uv = lerpUV(v0.uv, v1.uv, v2.uv,
                 weight0, weight1, weight2);

}
